/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pingouin;

import java.awt.Color;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Hippolyte
 */
public class Partie {

    public static PartieThread pt;
    public static TServeurRessources st;
    public static TServeurCoord ct;
    public static boolean reseau;
    public static boolean serveur;
    public static Ressources ressources;
    public static InetAddress adresseServeur;

    public Partie() {

        ressources = new Ressources();

        pt = new PartieThread(this);
        st = new TServeurRessources(this);

        ct = new TServeurCoord(this);

    }

    public void init(int nbJoueur, int nbOrdi, int niv, boolean res) {

        ressources.joueurs = new ArrayList<>();
        ressources.hexas = new ArrayList<>();
        ressources.joues = new ArrayList<>();
        ressources.messages = new ArrayList<>();
        ressources.JoueurEnCours = null;
        ressources.PingouinSelectionne = null;
        ressources.etatPartie = "";
        ressources.deplacementOk = false;


        reseau = res;
        serveur = true;


        System.out.println("reseau ==> " + reseau);

        st.start();

        System.out.println("initPlateau");

        initPlateau();

        System.out.println("initJoueur");

        initJoueurs(nbJoueur, nbOrdi, niv);


    }

    public static void initPlateau() {

        ressources.hexas.add(new Hexa(1, 0, 0, 2, 9, 0, 0, 1, 1));
        ressources.hexas.add(new Hexa(2, 0, 0, 3, 10, 9, 1, 1, 2));
        ressources.hexas.add(new Hexa(3, 0, 0, 4, 11, 10, 2, 1, 3));
        ressources.hexas.add(new Hexa(4, 0, 0, 5, 12, 11, 3, 1, 4));
        ressources.hexas.add(new Hexa(5, 0, 0, 6, 13, 12, 4, 1, 5));
        ressources.hexas.add(new Hexa(6, 0, 0, 7, 14, 13, 5, 1, 6));
        ressources.hexas.add(new Hexa(7, 0, 0, 8, 15, 14, 6, 1, 7));
        ressources.hexas.add(new Hexa(8, 0, 0, 0, 0, 15, 7, 1, 8));

        ressources.hexas.add(new Hexa(9, 1, 2, 10, 17, 16, 0, 2, 1));
        ressources.hexas.add(new Hexa(10, 2, 3, 11, 18, 17, 9, 2, 2));
        ressources.hexas.add(new Hexa(11, 3, 4, 12, 19, 18, 10, 2, 3));
        ressources.hexas.add(new Hexa(12, 4, 5, 13, 20, 19, 11, 2, 4));
        ressources.hexas.add(new Hexa(13, 5, 6, 14, 21, 20, 12, 2, 5));
        ressources.hexas.add(new Hexa(14, 6, 7, 15, 22, 21, 13, 2, 6));
        ressources.hexas.add(new Hexa(15, 7, 8, 0, 23, 22, 14, 2, 7));

        ressources.hexas.add(new Hexa(16, 0, 9, 17, 24, 0, 0, 3, 1));
        ressources.hexas.add(new Hexa(17, 9, 10, 18, 25, 24, 16, 3, 2));
        ressources.hexas.add(new Hexa(18, 10, 11, 19, 26, 25, 17, 3, 3));
        ressources.hexas.add(new Hexa(19, 11, 12, 20, 27, 26, 18, 3, 4));
        ressources.hexas.add(new Hexa(20, 12, 13, 21, 28, 27, 19, 3, 5));
        ressources.hexas.add(new Hexa(21, 13, 14, 22, 29, 28, 20, 3, 6));
        ressources.hexas.add(new Hexa(22, 14, 15, 23, 30, 29, 21, 3, 7));
        ressources.hexas.add(new Hexa(23, 15, 0, 0, 0, 30, 22, 3, 8));

        ressources.hexas.add(new Hexa(24, 16, 17, 25, 32, 31, 0, 4, 1));
        ressources.hexas.add(new Hexa(25, 17, 18, 26, 33, 32, 24, 4, 2));
        ressources.hexas.add(new Hexa(26, 18, 19, 27, 34, 33, 25, 4, 3));
        ressources.hexas.add(new Hexa(27, 19, 20, 28, 35, 34, 26, 4, 4));
        ressources.hexas.add(new Hexa(28, 20, 21, 29, 36, 35, 27, 4, 5));
        ressources.hexas.add(new Hexa(29, 21, 22, 30, 37, 36, 28, 4, 6));
        ressources.hexas.add(new Hexa(30, 22, 23, 0, 38, 37, 29, 4, 7));

        ressources.hexas.add(new Hexa(31, 0, 24, 32, 39, 0, 0, 5, 1));
        ressources.hexas.add(new Hexa(32, 24, 25, 33, 40, 39, 31, 5, 2));
        ressources.hexas.add(new Hexa(33, 25, 26, 34, 41, 40, 32, 5, 3));
        ressources.hexas.add(new Hexa(34, 26, 27, 35, 42, 41, 33, 5, 4));
        ressources.hexas.add(new Hexa(35, 27, 28, 36, 43, 42, 34, 5, 5));
        ressources.hexas.add(new Hexa(36, 28, 29, 37, 44, 43, 35, 5, 6));
        ressources.hexas.add(new Hexa(37, 29, 30, 38, 45, 44, 36, 5, 7));
        ressources.hexas.add(new Hexa(38, 30, 0, 0, 0, 45, 37, 5, 8));

        ressources.hexas.add(new Hexa(39, 31, 32, 40, 47, 46, 0, 6, 1));
        ressources.hexas.add(new Hexa(40, 32, 33, 41, 48, 47, 39, 6, 2));
        ressources.hexas.add(new Hexa(41, 33, 34, 42, 49, 48, 40, 6, 3));
        ressources.hexas.add(new Hexa(42, 34, 35, 43, 50, 49, 41, 6, 4));
        ressources.hexas.add(new Hexa(43, 35, 36, 44, 51, 50, 42, 6, 5));
        ressources.hexas.add(new Hexa(44, 36, 37, 45, 52, 51, 43, 6, 6));
        ressources.hexas.add(new Hexa(45, 37, 38, 0, 53, 52, 44, 6, 7));

        ressources.hexas.add(new Hexa(46, 0, 39, 47, 54, 0, 0, 7, 1));
        ressources.hexas.add(new Hexa(47, 39, 40, 48, 55, 54, 46, 7, 2));
        ressources.hexas.add(new Hexa(48, 40, 41, 49, 56, 55, 47, 7, 3));
        ressources.hexas.add(new Hexa(49, 41, 42, 50, 57, 56, 48, 7, 4));
        ressources.hexas.add(new Hexa(50, 42, 43, 51, 58, 57, 49, 7, 5));
        ressources.hexas.add(new Hexa(51, 43, 44, 52, 59, 58, 50, 7, 6));
        ressources.hexas.add(new Hexa(52, 44, 45, 53, 60, 59, 51, 7, 7));
        ressources.hexas.add(new Hexa(53, 45, 0, 0, 0, 60, 52, 7, 8));

        ressources.hexas.add(new Hexa(54, 46, 47, 55, 0, 0, 0, 8, 1));
        ressources.hexas.add(new Hexa(55, 47, 48, 56, 0, 0, 54, 8, 2));
        ressources.hexas.add(new Hexa(56, 48, 49, 57, 0, 0, 55, 8, 3));
        ressources.hexas.add(new Hexa(57, 49, 50, 58, 0, 0, 56, 8, 4));
        ressources.hexas.add(new Hexa(58, 50, 51, 59, 0, 0, 57, 8, 5));
        ressources.hexas.add(new Hexa(59, 51, 52, 60, 0, 0, 58, 8, 6));
        ressources.hexas.add(new Hexa(60, 52, 53, 0, 0, 0, 59, 8, 7));

        initPoissons();

        setAllVoisinsAuto();
    }

    public static void setAllVoisinsAuto() {
        for (Hexa h : ressources.hexas) {
            h.setVoisinAuto();
        }
    }

    public static void initJoueurs(int nbJoueur, int nbOrdi, int niv) {

        String[] couleur = new String[4];
        Color[] color = new Color[4];

        couleur[0] = "Bleu";
        couleur[1] = "Rouge";
        couleur[2] = "Vert";
        couleur[3] = "Violet";

        color[0] = Color.BLUE;
        color[1] = Color.RED;
        color[2] = Color.GREEN;
        color[3] = Color.MAGENTA;

        int nbJoueursTotal = nbJoueur + nbOrdi;

        if (nbJoueursTotal <= 2) {
            ressources.nbPingouin = 4;
        } else if (nbJoueursTotal == 3) {
            ressources.nbPingouin = 3;
        } else {
            ressources.nbPingouin = 2;
        }

        int tempJoueur = 0;

        if (nbJoueur > 0) {
            Joueur j = new Joueur(tempJoueur, couleur[tempJoueur], color[tempJoueur], false, 0, false, reseau);
            for (int i = 0; i < ressources.nbPingouin; i++) {
                j.pingouins.add(new Pingouin(i));
            }
            ressources.joueurs.add(j);
            tempJoueur++;
        }

        for (int nbJ = 1; nbJ < nbJoueur; nbJ++) {
            Joueur j = new Joueur(tempJoueur, couleur[tempJoueur], color[tempJoueur], false, 0, false, false);
            for (int i = 0; i < ressources.nbPingouin; i++) {
                j.pingouins.add(new Pingouin(i));
            }
            ressources.joueurs.add(j);
            tempJoueur++;
        }

        for (int nbJ = 0; nbJ < nbOrdi; nbJ++) {
            Joueur j = new Joueur(tempJoueur, couleur[tempJoueur], color[tempJoueur], true, niv, false, true);
            for (int i = 0; i < ressources.nbPingouin; i++) {
                j.pingouins.add(new Pingouin(i));
            }
            ressources.joueurs.add(j);
            tempJoueur++;
        }

    }

    public static void initPoissons() {
        ArrayList<Integer> nb = new ArrayList<>();
        int rand;
        for (int i = 0; i < 30; i++) {
            nb.add(1);
        }
        for (int i = 0; i < 20; i++) {
            nb.add(2);
        }
        for (int i = 0; i < 10; i++) {
            nb.add(3);
        }
        for (Hexa h : ressources.hexas) {
            rand = (int) (Math.random() * nb.size());
            h.nbPoisson = nb.get(rand);
            nb.remove(rand);
        }
    }

    public static boolean placeLibre(int num) {
        if (ressources.joues.contains(Hexa.getCase(num))) {
            return false;
        }
        for (Joueur j : ressources.joueurs) {
            for (Pingouin p : j.pingouins) {
                if (p.hexa != null && p.hexa.num == num
                        && ressources.PingouinSelectionne != null
                        && !ressources.PingouinSelectionne.equals(p)) {
                    return false;
                }
            }
        }
        return true;
    }

    public void demarrePartie() {


        pt.start();

        ct.start();

        envoiSocket();

    }

    public void choixCases() {

        ressources.etatPartie = "choix";

        for (int i = 0; i < ressources.nbPingouin; i++) {
            for (Joueur j : ressources.joueurs) {
                ressources.PingouinSelectionne = j.pingouins.get(i);

                ressources.JoueurEnCours = j;

                if (j.ordi) {
                    try {
                        Thread.sleep(250);
                    } catch (InterruptedException ex) {
                        Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    j.choixOrdi();

                } else {

                    ressources.messages.add("Joueur " + j.nom + " choisissez une case");
                    synchronized (pt.awake) {
                        try {
                            pt.awake.wait();
                        } catch (InterruptedException ex) {
                            Logger.getLogger(Partie.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    }
                }

                envoiPartie();

                System.out.println(ressources.PingouinSelectionne.hexa.num + "");

            }
        }


    }

    public void jouer() {

        ressources.etatPartie = "jeu";
        while (!partieFinie()) {
            for (Joueur j : ressources.joueurs) {


                ressources.PingouinSelectionne = null;
                ressources.JoueurEnCours = j;
                ressources.messages.add("Joueur " + j.nom + " à vous de jouer ("
                        + j.deplacementPossibles() + " deplacements possibles)");

                ArrayList<Pingouin> depPossible = j.PingouinDeplacementPossibles();

                if (depPossible.size() > 0) {

                    if (j.ordi) {
                        try {
                            Thread.sleep(250);
                        } catch (InterruptedException ex) {
                            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
                        }
                        j.joueOrdi();
                    } else {

                        if (depPossible.size() == 1) {
                            ressources.PingouinSelectionne = depPossible.get(0);
                        }

                        ressources.deplacementOk = false;

                        synchronized (pt.awake) {
                            try {
                                pt.awake.wait();
                            } catch (InterruptedException ex) {
                                Logger.getLogger(Partie.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                    checkPingouinFini();
                    envoiPartie();
                }
            }
        }

//        checkPingouinFini();

        Joueur gagnant = Partie.gagnant();

        ressources.messages.add("Gagnant = " + gagnant.nom
                + " avec " + gagnant.nbPoisson() + " poissons");
    }

    public static boolean partieFinie() {
        for (Joueur j : ressources.joueurs) {
            if (j.deplacementPossibles() > 0) {
                return false;
            }
        }
        return true;
    }

    public static void checkPingouinFini() {
        for (Joueur j : ressources.joueurs) {
            for (Pingouin p : j.pingouins) {
                p.checkFini();
            }
        }
    }

    public static Joueur gagnant() {
        int maxPoisson = 0;
        Joueur gagnant = null;
        for (Joueur j : ressources.joueurs) {
            if (j.nbPoisson() > maxPoisson) {
                maxPoisson = j.nbPoisson();
                gagnant = j;
            }
        }
        return gagnant;
    }

    public static void envoiPartie() {

        if (reseau) {
            synchronized (st.awake) {
                st.awake.notify();
            }
        }

    }

    public void envoiSocket() {

        System.out.println("essaye envoi socket");

        for (Joueur j : ressources.joueurs) {
            if (!j.surCetOrdi && j.address != null) {
                System.out.println("envoi socket");
                try {
                    Socket s = new Socket(j.address, TServeurRessources.PORT);
                    OutputStream os = s.getOutputStream();
                    ObjectOutputStream oos = new ObjectOutputStream(os);
                    oos.writeObject(ressources);
                    oos.close();
                    os.close();
                    s.close();
                } catch (IOException ex) {
                    Logger.getLogger(Partie.class.getName()).log(Level.SEVERE, null, ex);
                }


            }
        }
    }

    public static void actionClic(int x, int y) {
        Hexa h = Hexa.findHexa(x, y);
        if(h == null){
            return;
        }
        if (ressources.etatPartie.equalsIgnoreCase("choix")) {

            if (h.nbPoisson == 1) {
                if (Partie.placeLibre(h.num)) {
                    ressources.PingouinSelectionne.hexa = h;
                    synchronized (Partie.pt.awake) {
                        Partie.pt.awake.notify();
                    }
                }
            } else {
                ressources.messages.add("Veuillez vous mettre sur une case d'un poisson");
            }


        } else if (ressources.etatPartie.equalsIgnoreCase("jeu")) {


            if (ressources.PingouinSelectionne != null) {

                if (h.equals(ressources.PingouinSelectionne.hexa)) {
                    ressources.PingouinSelectionne = null;
                    Partie.envoiPartie();
                } else {
                    if (ressources.PingouinSelectionne.deplacer(h)) {
                        synchronized (Partie.pt.awake) {
                            Partie.pt.awake.notify();
                        }
                    }
                }

            } else {
                ressources.PingouinSelectionne = Pingouin.getPingouin(h);
                Partie.envoiPartie();
            }
        }
    }

    public static InetAddress getByIpAddress(String address) {
        byte[] add = new byte[4];
        System.out.println(address.split("\\.")[0] + " " + address.split("\\.")[1] + " " + address.split("\\.")[2] + " " + address.split("\\.")[3]);
        add[0] = Byte.parseByte(address.split("\\.")[0]);
        add[1] = Byte.parseByte(address.split("\\.")[1]);
        add[2] = Byte.parseByte(address.split("\\.")[2]);
        add[3] = Byte.parseByte(address.split("\\.")[3]);
//        InetAddress adda;

        InetAddress inet = null;

        try {
            inet = InetAddress.getByAddress(add);
        } catch (UnknownHostException ex) {
            Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
        }

        return inet;

    }
}
